package com.atguigu.mybatisplus.web;

import com.atguigu.mybatisplus.entity.User;
import com.atguigu.mybatisplus.service.UserService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.concurrent.CompletableFuture;

/**
 * @author zhuzi
 * 2022/8/10 21:26
 * 事务测试
 * https://www.bilibili.com/video/BV1hG411s7aD
 */
//@Transactional(propagation= Propagation.SUPPORTS,readOnly=true)
@Slf4j
@RestController
@RequestMapping(path = "tx")
public class TxController {
    @Autowired
    UserService userService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private TransactionDefinition transactionDefinition;
    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Transactional(rollbackFor = Exception.class)
    @GetMapping("errs")
    public ResponseEntity<String> errors() {

        try {
            User ts = new User().setAge(28).setEmail("ss.com").setName("ts");
            System.out.println(ts);
            userService.save(ts);
            System.out.println(1 / 0);
        } catch (Exception e) {
            // 可以回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return ResponseEntity.ok("ok");
    }

    @GetMapping("aop")
    public ResponseEntity<String> aoptest() {
        //add();//直接调用是不生效的

        // 这样是生效的|https://www.jianshu.com/p/28a29070f530| AopContext.currentProxy()解决同类中调用嵌套方法AOP失效
        //((TxController) AopContext.currentProxy()).add();//方法必须是public才行

        add();//解决自调用，在类上添加 也行 @Transactional(propagation= Propagation.SUPPORTS,readOnly=true)

        return ResponseEntity.ok("aop");
    }

    @Transactional(rollbackFor = Exception.class)
    protected void add() {
        User ts = new User().setAge(28).setEmail("ss.com").setName("testAop");
        System.out.println(ts);
        userService.save(ts);
        System.out.println(1 / 0);
    }

    @GetMapping("sync")
    public ResponseEntity sync() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        CompletableFuture<Void> asyncReturn = CompletableFuture.runAsync(() -> {
            // 每一个线程都来共享之前的请求数据
            //RequestContextHolder.setRequestAttributes(requestAttributes);
            // 手动开启事务
            TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
            try {
                User ts = new User().setAge(28).setEmail("ss.com").setName("testAop");
                System.out.println(ts);
                userService.save(ts);
                System.out.println(1 / 0);
                //手动提交事务
                platformTransactionManager.commit(transactionStatus);
            } catch (Exception e) {
                //手动回滚事务
                platformTransactionManager.rollback(transactionStatus);
            }
            //下面这个不生效
            //TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        });
        return ResponseEntity.ok("sync");
    }

    @Transactional(rollbackFor = Exception.class)
    @GetMapping("sync2")
    public ResponseEntity syncSer() {
        userService.sync();
        return ResponseEntity.ok("sync2");
    }

    /**
     * 回滚点
     *
     * @return
     */
    @GetMapping("savePoint")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity savePoint() {
        Object savepoint = null;
        try {
            userService.update(new LambdaUpdateWrapper<User>().eq(User::getId, 1).set(User::getAge, 28));
            userService.save(new User().setAge(27).setName(RandomStringUtils.randomAlphabetic(5)).setId(6L));
            savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
            userService.save(new User().setAge(27).setName(RandomStringUtils.randomAlphabetic(5)));
            int i = 1 / 0;
        } catch (Exception e) {
            log.error("发生异常", e);
            //手工回滚事务
            TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
        }
        return ResponseEntity.ok("ok");
    }
}
